home *** CD-ROM | disk | FTP | other *** search
/ CU Amiga Super CD-ROM 23 / CU Amiga - Super CD-ROM 23 (June 1998).iso / CreatingGames / GameCreators / Inform / translators_manual.txt < prev   
Encoding:
Text File  |  1997-03-15  |  86.7 KB  |  2,323 lines

  1. ------------------------------------------------------------------------------
  2.                         Inform Translator's Manual
  3.  
  4.                               Graham Nelson
  5.                             9th December 1996
  6. ------------------------------------------------------------------------------
  7.    1   Introduction
  8.  
  9.    2   Teaching Inform to read your language
  10.  
  11.    2.1      What is Informese?
  12.    2.2      A grammar of Informese
  13.             (a) Commands
  14.             (b) Verb phrases
  15.             (c) Noun phrases
  16.             (d) Descriptors
  17.             (e) Nouns
  18.             (f) Example
  19.             (g) Grammatical features not present in Informese
  20.    2.3      Gender, number and animation (GNA) of noun phrases
  21.    2.4      The alphabet
  22.    2.5      Plural dictionary words
  23.    2.6      Dealing with flexion in noun phrases using grammar tokens
  24.    L.0      Organisation of language definition files
  25.    L.I.1    Version number and alphabet
  26.    L.I.2    Compass objects
  27.    L.II.1   Informese vocabulary: miscellaneous
  28.    L.II.2   Informese vocabulary: pronouns
  29.    L.II.3   Informese vocabulary: descriptors
  30.    L.II.4   Informese vocabulary: numbers
  31.    L.III.1  Translating natural language to Informese
  32.  
  33.    3   Teaching Inform to write your language
  34.  
  35.    3.1      The GNA of object names
  36.    3.2      Flexion in object names
  37.    L.IV.1   Default genders and contraction forms
  38.    L.IV.2   How to print: articles
  39.    L.IV.3   How to print: direction names
  40.    L.IV.4   How to print: numbers
  41.    L.IV.5   How to print: the time of day
  42.    L.IV.6   How to print: verbs
  43.    L.IV.7   How to print: menus
  44.    L.IV.8   How to print: miscellaneous short messages
  45.    L.IV.9   How to print: LibraryMessages
  46.  
  47. ------------------------------------------------------------------------------
  48.  
  49.    1.  Introduction
  50.    ----------------
  51.  
  52.      "The corresponding Kivunjo construction [to the English dative]
  53.      is called the applicative... [it] fits entirely inside the verb,
  54.      which has seven prefixes and suffixes, two moods and fourteen
  55.      tenses; the verb agrees with its subject, its object and its
  56.      benefactive nouns, each of which has sixteen genders."
  57.   
  58.      -- Steven Pinker, "The Language Instinct".  (Kivunjo is spoken
  59.         only in certain villages on the slopes of Mount Kilimanjaro.)
  60.  
  61.      "_It_, hell.  She had _Those_."
  62.      
  63.      -- Dorothy Parker, reviewing a book called "It", whose hero and
  64.         heroine supposedly had _It_, or sex appeal.
  65.  
  66.  
  67. Designing a computer interface to cope with the full range of human
  68. languages is far from simple.  Three things make matters easier for Inform:
  69.  
  70.  (a) Most languages form imperative commands in a similar fashion to
  71.      English (perhaps Chomsky's Universal Grammar of human language,
  72.      if there is one, allows little variation).
  73.  (b) Inform is probably only going to be used with Romance, and perhaps
  74.      a few Ugric languages: relations between these are close for
  75.      historical reasons.
  76.  (c) Inform's internal workings (its parser and verb library) deal only
  77.      with a small part of grammar: present tense, imperative verbs and
  78.      so on.
  79.  
  80. The present systems have been made as flexible as reasonably possible,
  81. but have also made compromises.  There will still be languages which it is
  82. extremely difficult to translate Inform to (Hebrew, for instance, where
  83. vowels are conventionally omitted, to leave an ambiguous text which must be
  84. understood in context).  English is a non-inflected language.  That is,
  85. one in which word endings tend not to vary according to grammatical situation:
  86.  
  87.     take a brown dog
  88.     take the brown dog
  89.     give a biscuit to the brown dog
  90.  
  91. In German, the corresponding words to "brown" and "dog" would each have
  92. inflected to agree with the definite or indefinite article, and "to the
  93. brown dog" would be expressed by writing "brown dog" in the dative case,
  94. inflecting it again.  (Even English has a few inflections, inherited from
  95. Old English -- which was an inflected language: I do, you do, he does; I have,
  96. you have, he has.)
  97.  
  98. Most languages are more heavily inflected than English, some (like Kivunjo
  99. or Finnish) crushingly so.  Yet the Inform parser is really modelled on a
  100. non-inflected language.  A translator will face two basic tasks:
  101.  
  102.  (a) Translating many small pieces of text, which should be easy but
  103.      probably quite tedious.
  104.  (b) Writing short pieces of code, and grammar tokens, to try to remove
  105.      inflections, stripping out prefixes and suffixes from words as
  106.      needed.
  107.  
  108. The translator will probably want to compromise in a few places, omitting
  109. tricky but not really necessary features of the language.  For instance,
  110. in German, adjectives take forms agreeing with whether their noun takes
  111. a definite or indefinite article:
  112.  
  113.      ein großer Mann      = a tall man
  114.      der große Mann       = the tall man
  115.  
  116. This is a feature which we cannot compromise on.  But German also has a
  117. "neutral" form for adjectives, used in sentences like
  118.  
  119.      Der Mann ist groß    = The man is tall
  120.  
  121. Now it could be argued that if the parser asks a question like
  122.  
  123.      Whom do you mean, the tall man or the short man?
  124.  
  125. then the player ought to be able to reply "groß".  I think this just isn't
  126. worth the trouble.  As another example from German, is it essential for the
  127. parser to recognise commands put in the polite form when addressed to somebody
  128. other than the player?  For instance,
  129.  
  130.      freddy, Öffne den ofen              =  Freddy, open the oven
  131.      herr krÜger, Öffnen sie den ofen    =  Mr Krueger, open the oven
  132.  
  133. demonstrate forms to be used if Freddy is a familiar friend and Mr Krueger
  134. a mere acquaintance.  A translator might go to the trouble of implementing
  135. this (it's not impossible), but I suspect I'd not bother, and simply tell
  136. players always to use the familiar form.
  137.  
  138. The translator will also face choices.  I can imagine two rather different
  139. translations into French, one which expects players to type commands using
  140. accented letters, and one which expects them to ignore accents and simply
  141. type A to Z.  (After all, some capitalised French titles omit accents, and
  142. accents can be a nuisance on some computer keyboards.)
  143.  
  144. Another range of choices concerns how the computer is to be addressed.
  145. Many languages have different forms of address to people who are familiar
  146. and to strangers, as in the example of Freddy and Mr Krueger.  Is the
  147. computer familiar?  I suggest so, but a translator is free to disagree.
  148. For that matter, does the player address the computer or the main character
  149. of the game?  It depends on one's point of view.  In English it makes no
  150. difference, but there are languages where an imperative verb agrees with
  151. the gender of the person being addressed.  Is the computer male?  Is it
  152. still male if the game's main character is female?
  153.  
  154. Finally, there are also dialect forms.  A French translation will be almost,
  155. but not quite, the same as a Francophone Canadian or Belgian one.
  156.  
  157. I suggest that for such choices, the translator may want to write his
  158. language definition file to cope with either possibility.  For example,
  159. something like
  160.  
  161.     #ifdef DIALECT_FRANCOPHONE;
  162.     print "septante";
  163.     #ifnot;
  164.     print "soixante-dix";
  165.     #endif;
  166.  
  167. would enable the same definition file to be used by Quebecois authors
  168. and paid-up members of the Academie Francaise alike.  (The "English.h"
  169. file already has such a constant: DIALECT_US, which uses US spellings
  170. and number conventions in the very few instances where they differ from
  171. English ones.)
  172.  
  173. Would anyone care to write a language definition file for Black English
  174. Vernacular?
  175.  
  176.  
  177. Inform's library 6/3 comes as a set of 8 files, not 7 as in library 6/2:
  178. the new file is called "English.h" and is a definition of the English language.
  179. A new ICL path variable (new in Inform 6.10, that is) called "language_name"
  180. allows this to be changed:
  181.  
  182.     inform +language_name=French voliere
  183.  
  184. compiles "voliere" using "French.h" in place of "English.h".
  185.  
  186. Files like "French.h" and "English.h" are called "language definitions", and
  187. this manual tells you how to draft a new language definition file.
  188.  
  189. My ambition is for a stock of language definitions to be built up and
  190. publically archived.  The author of an Inform game will probably still have
  191. to speak English (after all, the manuals are in English, and so is text
  192. produced by the special debugging verbs) but players will not.  In any case,
  193. there have been fringe benefits to this project -- the English Inform library
  194. is becoming more sensitive to number and "a" becoming "an" before a vowel,
  195. for instance.
  196.  
  197. Translators need to produce one other file: a translation of the "Grammar.h"
  198. file into their own languages.  I hope to use the conventional filenames:
  199.  
  200.     FrenchG.h
  201.     GermanG.h
  202.  
  203. and so forth to refer to these.
  204.  
  205.  
  206. I should like to thank the following people, whose thoughtful replies to
  207. the discussion document have improved this one: Torbj|rn Andersson, Joachim
  208. Baumann, Paul David Doherty, Bjorn Gustavsson, Aapo Haapanen, JP Ikaheimonen,
  209. Bob Newell "mon oncle", Linards Ticmanis.  How else could I have learned
  210. the palindromic Finnish word for soap dealer, "saippuakauppias"?  Finally,
  211. I must also thank Jose Luis Diaz, whose translation of the Inform 5/12
  212. library into Spanish first introduced me to the complexity of the problem.
  213.  
  214. Torbj|rn made the helpful suggestion that in the French version of "Curses",
  215. perhaps the player could look for a tourist map of London.  Seriously,
  216. if anyone out there would like to translate any of my games, please feel free
  217. to get in touch.  I suspect a translation of "Advent" might be a better
  218. place to begin.
  219.  
  220.                                                           Graham Nelson
  221.                                                           5th December 1996
  222. ------------------------------------------------------------------------------
  223.  
  224.  
  225.    2.  Teaching Inform to read your language
  226.    -----------------------------------------
  227.  
  228.    2.1  What is Informese?
  229.    -----------------------
  230.  
  231. The Inform parser understands a simple language, modelled on a small part of
  232. English, which we will call "Informese".
  233.  
  234. The first, fairly easy, job of the translator is to change the vocabulary
  235. of Informese (the dictionary, so to speak) so that it matches the new
  236. language.  For instance, in English, Informese uses words like "other"
  237. and "another" in the category of "other-words" (see below).  A translator
  238. to French will probably change these to "autre".
  239.  
  240. Once this is done, the Inform parser will understand commands which are
  241. neither good English nor, at least in some cases, good French.  For
  242. example:
  243.  
  244.    jetez le boite dans lui
  245.  
  246. is good Informese (using French vocabulary) but it is not good French --
  247. the correct French would be
  248.  
  249.    jetez le boite dedans
  250.  
  251. where the word "dedans" is a part of French grammar which doesn't correspond
  252. to a single part of Informese.  So the second job of the translator is to
  253. write an Inform program to translate what the player typed (real French)
  254. into what the parser can understand (French-vocabulary Informese).  For
  255. most Romance languages, only a few simple transformations will be needed, but
  256. for some heavily inflected or agglutinizing languages the translation process
  257. may need a substantial program.  This is probably the hardest job an Inform
  258. translator has.
  259.  
  260. The biggest difference between Informese and non-English languages is that
  261. Informese does not glue together different words which belong to different
  262. grammatical constructs in Informese (as in the above case, where Informese
  263. would not glue together "dans" and "lui" into "dedans").  But this is
  264. common in non-English languages.  (E.g., Spanish "cogela" ("take it") must
  265. be translated into "coge la" to become good Informese.)
  266.  
  267. Better news is that Informese can be configured automatically to have
  268. up to three genders and to recognise cases of nouns, even though these
  269. features lie dormant in the English parser.  Informese is not checked in
  270. absolute detail by the parser: the player can usually get away with typing
  271. the wrong gender for something in French, for instance (as in "la ciel").
  272. But the parser is not ignoring gender: if the player refers to an object
  273. as simply "la", the parser will match it against something whose short name
  274. is female singular.
  275.  
  276.  
  277.    2.2  A grammar for Informese
  278.    ----------------------------
  279.  
  280. (a) Commands
  281.  
  282. A command to an Inform game should be one of:
  283.  
  284.     oops <word>                     correct the last command by putting
  285.                                     the <word> in to replace whatever seemed
  286.                                     to be incorrect
  287.     <action>                        perform this action
  288.     <noun phrase>, <action>         tell someone else to perform the action
  289.  
  290. An <action> consists of a sequence of verb phrases, divided up by full stops
  291. or "then-words": a "then-word" is a word like "then" (in English).  E.g.,
  292.  
  293.     take sword. east. put sword in stone
  294.  
  295. is broken into the obvious sequence of three verb phrases, each of which
  296. is parsed and acted on in turn.  (It's important not to parse them all
  297. at once: the meaning of the noun phrase "stone" depends on where the player
  298. is, and by the time this command is reached, the player will not be where
  299. he is now.)
  300.  
  301.  
  302. (b) Verb phrases
  303.  
  304. A verb phrase is either
  305.  
  306.     again                           the same as the most recent verb phrase
  307.                                     typed in
  308.  
  309. or takes the form
  310.  
  311.     <imperative verb> <grammar line>
  312.  
  313. The "imperative" is the form of the verb used for orders or instructions:
  314. e.g., "open" in "open the window" (though English is a poor example since
  315. the imperative looks the same as the infinitive); "ouvrez" in "ouvrez la
  316. fenetre" (French).  In most languages, even some in which verbs usually
  317. follow objects (e.g. Latin), the imperative verb comes at the start of a
  318. verb phrase.  If not, some coding will be needed (see later).
  319.  
  320. It is possible for the verb to be more than one word, using an UnknownVerb
  321. routine (for example).
  322.  
  323. Grammar lines are documented elsewhere, and most Inform programmers feel
  324. familiar with them.  Each token has one of four kinds of outcome:
  325.  
  326.     Outcome:                       Example tokens producing this:
  327.     a "noun phrase"                noun, multiheld, scope=MyScope, edible,
  328.                                    creature, noun=CagedCreature, etc.
  329.     a "preposition"                'into', 'against'
  330.     a number                       number
  331.     a chunk of unparsed text       special, topic
  332.  
  333. (A general parsing routine may have any of these four outcomes.)  Note that
  334. the term "preposition" is being used here to mean any word written in
  335. quotes as a grammar token.  This usually corresponds to the grammatical
  336. meaning of "preposition" (for instance, "into" and "against" are both
  337. prepositions in English) but need not do so.
  338.  
  339.  
  340. (c) Noun phrases
  341.  
  342. A "noun phrase" is a string of words which refer to a single object or
  343. collection of objects in the game, with more or less exactness.  In English,
  344. typical Inform noun phrases are:
  345.  
  346.     it
  347.     rucksack
  348.     shield, dagger
  349.     the blue box
  350.     a box and the compass
  351.     nine bronze coins
  352.     everything except the green crown
  353.     all the swords
  354.  
  355. (Thus a "noun phrase" in Inform terms is any piece of text which can match
  356. against one of the grammar tokens "noun", "multi", etc.)
  357.  
  358. Inform divides up noun phrases into three kinds of word:
  359.  
  360.     "Connectives" are conjunctions or disjunctions, that is, words which
  361.     can join noun phrases together.  The Inform parser regards a comma as
  362.     a connective, and (in English) also recognises "and", "but" and "except".
  363.  
  364.     "Descriptors" are words which clarify the noun to follow, such as
  365.     "the", "every", "my" or "all".
  366.  
  367.     "Nouns" are words matched against particular game objects.
  368.  
  369. Although the expected form is
  370.  
  371.          noun phrase
  372.          |         |
  373.          |         |
  374.      descriptors  nouns
  375.  
  376. (note that descriptors are expected to precede nouns), in fact both
  377. halves are optional:
  378.  
  379.     the balloon         descriptor, noun
  380.     all                 descriptor
  381.     train               noun
  382.  
  383. are all legal Inform noun phrases, and even text like
  384.  
  385.     take a
  386.  
  387. is a legal Inform verb phrase.
  388.  
  389.  
  390. (d) Descriptors
  391.  
  392. There are five kinds of descriptor, as follows:
  393.  
  394.     "Articles" are words indicating whether a particular object is being
  395.     referred to, or merely one of a range.  Thus there are two kinds of
  396.     article, "definite" and "indefinite".  E.g., English has four articles:
  397.  
  398.            "the"               definite
  399.            "a", "an", "some"   indefinite
  400.  
  401.     "All-words" are words which behave like the English word "all", that
  402.     is, which match against a whole range of objects.  (To Informese this
  403.     is effectively a "pluralising article" -- it behaves like an article
  404.     meaning "expect a collection of things to follow".  In this respect,
  405.     Informese behaves like some natural languages: Tagalog, for instance.)
  406.  
  407.     "Other-words" are words behaving like "other", which Inform interprets
  408.     as "other than the one I am holding".  Thus, if the player is holding
  409.     a sword in a room where there's also a sword on the floor, then "examine
  410.     other sword" would refer to the one on the floor.
  411.  
  412.     "Demanding numbers" are numbers like "nine" in "nine bronze coins",
  413.     which demand that a certain number of items are needed.
  414.  
  415.     "Possessive adjectives" are adjectives indicating ownership by someone
  416.     or something whose meaning is held in a pronoun, such as "my" (belonging
  417.     to "me") or "his" (belonging to "him") or "son" (French: belonging to
  418.     "lui").  Note that they are adjectives and not pronouns.
  419.  
  420.  
  421. (e) Nouns
  422.  
  423. There are three kinds of noun, as follows:
  424.  
  425.     "Names" are words matched against particular objects.  Usually
  426.     (that is, unless the object in question has a "parse_name" routine
  427.     attached), these will just be the words found in an object's "name"
  428.     property.  E.g., for the object defined as:
  429.  
  430.            Object -> "blue box"
  431.              with name 'blue' 'box';
  432.  
  433.     the words "blue" and "box" are both names.  Note that the Inform parser
  434.     does not make the grammatical distinction between nouns and adjectives.
  435.     This makes it simpler and more efficient (though not all designers agree
  436.     that it's a good idea, and some write parse_name routines to keep
  437.     nouns and adjectives separate -- see the "Designer's Manual" for an
  438.     example of how to do this).
  439.  
  440.     "Me-words" are words which behave like the English word "me", that is,
  441.     which refer to the player-object.  (Grammatically, such words are
  442.     examples of relative pronouns, but the Inform parser treats them
  443.     differently from other pronouns.)  Note that they refer to the player,
  444.     not the "actor" (the person to whom the command is directed) --
  445.     in "mark, give me the bomb", "me" refers to the speaker, not to Mark.
  446.  
  447.     "Pronouns" are words which stand in the place of nouns and can only
  448.     be understood with reference back to what has previously been said.
  449.     To parse "put it on the table", Inform has to remember recent events:
  450.     if the previous command was "take sword", for instance, then "it" will
  451.     probably be understood as "the sword".
  452.  
  453.  
  454. (f) Example
  455.  
  456. Suppose the verb "put" has a grammar line reading
  457.  
  458.     * multiexcept 'into' noun ->
  459.  
  460. (as indeed it does in the English "grammar.h" library file).  Then the
  461. text
  462.  
  463.     conan, put all the swords into box
  464.  
  465. is parsed as
  466.                command
  467.                   |
  468.                 order
  469.                /  :  \
  470.               /   :   \
  471.     noun phrase   :    action
  472.               |   :       |
  473.             nouns :    verb phrase
  474.               |   :   /           \
  475.             name  :  /             \
  476.               :   : verb      grammar line____________________
  477.               :   :  :             |             |           |
  478.               :   :  :        noun phrase   preposition  noun phrase
  479.               :   :  :        |         |        :                 |
  480.               :   :  :   descriptors  nouns      :               nouns
  481.               :   :  :     |      |     |        :                 |
  482.               :   :  : all-word article name     :                name
  483.               :   :  :     :      :     :        :                 :
  484.             conan , put   all    the   swords   into              box
  485.  
  486.  
  487. (g) Grammatical features which Informese does not have
  488.  
  489. Of course there are endless points of grammar which Informese doesn't have,
  490. but here are some of the more surprising ones:
  491.  
  492.   adverbs: "run quickly east" would not normally be understood, unless of
  493.     course the designer arranged for "run quickly" to be effectively a
  494.     different verb from "run" (e.g. by writing some grammar lines beginning
  495.     with the token 'quickly', and others not beginning that way).
  496.  
  497.   adjectives and nouns are not distinguished from each other when
  498.     "names" are being parsed;
  499.  
  500.   objects are not normally named by description of their circumstances --
  501.     e.g., "the box on the floor" or "the priest's hat".  This is good news
  502.     for translators, as it avoids the need to work out a formal system
  503.     of genitives (in German, for instance).  Designers can still define
  504.     objects like
  505.  
  506.         Object -> "priest's hat"
  507.           with name 'hat' 'priest^s';
  508.  
  509.     that is, making genitive forms of words (e.g. "priest's") names on the
  510.     same basis as the noun ("hat").
  511.  
  512.   demonstrative adjectives ("this" and "that") are recognised by the
  513.     English version of Inform, but hardly anybody knows this or makes use of
  514.     it.  English is unusually simple in having only two d.a.'s, "this" and
  515.     "that": e.g. Spanish has three forms, for "this", "that" (nearby) and
  516.     "that" (far away"), and then has masculine, feminine, singular and
  517.     plural versions of each; and the structure of "celui-ci" and "celui-la"
  518.     in French is too complex to be worth the effort of parsing.  So I simply
  519.     propose not to translate this feature to languages other than English.
  520.  
  521.   other kinds of pronoun, such as:  
  522.     subject (nominative) pronouns ("I" in "I am happy");
  523.     interrogative pronouns ("What" in "What are you doing?");
  524.     demonstrative pronouns ("this" or "that" in "eat that");
  525.     possessive pronouns ("mine" in "Mine is a big car").
  526.  
  527.   pronominal adverbs: English does not have these.  A pronominal adverb
  528.     indicates that a verb should do something with, towards, in, etc. 
  529.     a noun whose meaning is that of a particular pronoun.  For example,
  530.     "dessous" in French ("under it"), or "darauf" (and "davon", etc.)
  531.     in German.
  532.  
  533.  
  534.    2.3  Gender, number and animation (GNA) of noun phrases
  535.    -------------------------------------------------------
  536.  
  537. "Gender": in most European languages, nouns divide up into masculine, feminine
  538.     (or sometimes neuter) forms.  Gender may be the only way to distinguish
  539.     otherwise identical nouns, as in French: "le faux", the forgery,
  540.     "la faux", the scythe.  There may be no satisfactory way to determine
  541.     the gender of a noun by any automatic rules (as in German).
  542.     Inform assumes there are no more than three genders.  Internally these
  543.     are called male, female and neuter (though, as we shall see, they do
  544.     not need to be used as such).
  545.  
  546. "Number": singular ("the hat") or plural ("the grapes").  Individual objects
  547.     in Inform games can have names of either number.  (Languages with more
  548.     than two numbers are rare -- Tagalog, or Filipino, has a third for
  549.     "pair of".  Inform does not directly support this.)
  550.  
  551. "Animation": Inform distinguishes between the animate (people and higher
  552.     animals) and the inanimate (objects, plants, lower animals).
  553.  
  554. Combining these three possibilities gives 12 possible combinations:
  555.  
  556.     (3 genders) * (2 numbers) * (2 animations) = 12
  557.  
  558. The combination is called the GNA of a noun phrase.  Inform uses this
  559. concept both when parsing and when printing out names of objects.
  560. Internally, GNAs are represented by numbers between 0 to 11:
  561.  
  562.                0     animate    singular    male
  563.                1                            female
  564.                2                            neuter
  565.                3                plural      male
  566.                4                            female
  567.                5                            neuter
  568.                6     inanimate  singular    male
  569.                7                            female
  570.                8                            neuter
  571.                9                plural      male
  572.               10                            female
  573.               11                            neuter
  574.  
  575. Not all possible GNAs will occur in all natural languages.  (In English,
  576. cases 6, 7, 9 and 10 never occur.  In French, 2, 5, 8 and 11 never occur.)
  577.  
  578.  
  579.    2.4  The alphabet
  580.    -----------------
  581.  
  582. Z-machine interpreters are now available for almost all machines which obey
  583. the Z-Machine Standard Document (November 1995), version 0.2.  Among other
  584. things this defined a standard set of character codes for accented and
  585. non-English letters, based loosely on the ISO Latin 1 convention.  Inform 6
  586. supports this set of accents and it may be useful to reprint the appropriate
  587. section of the Inform Designer's Manual (third edition, 1996) here:
  588.  
  589.  
  590. "Most accented characters are written as @, followed by an accent marker,
  591. then the letter on which the accent appears:
  592.  
  593.    @^   put a circumflex on the next letter: a,e,i,o,u,A,E,I,O or U
  594.    @'   put an acute on the next letter: a,e,i,o,u,y,A,E,I,O,U or Y
  595.    @`   put a grave on the next letter: a,e,i,o,u,A,E,I,O or U
  596.    @:   put a diaeresis on the next letter: a,e,i,o,u,A,E,I,O or U
  597.    @c   put a cedilla on the next letter: c or C
  598.    @~   put a tilde on the next letter: a,n,o,A,N or O
  599.    @\   put a slash on the next letter: o or O
  600.    @o   put a ring on the next letter: a or A
  601.  
  602. In addition, there are a few others:
  603.  
  604.    @ss  German sz
  605.    @<<  continental European quotation marks
  606.    @>>     
  607.    @ae  ligatures
  608.    @AE     
  609.    @oe     
  610.    @OE     
  611.    @th  Icelandic accents
  612.    @et     
  613.    @Th     
  614.    @Et     
  615.    @LL  pound sign
  616.    @!!  Spanish (upside-down) exclamation mark
  617.    @??  Spanish (upside-down) question mark
  618.  
  619. For instance,
  620.  
  621.     print "@AEsop's @oeuvres en fran@ccais, mon @'el@`eve!";
  622.     print "Na@:ive readers of the New Yorker will re@:elect Mr Clinton.";
  623.     print "Carl Gau@ss first proved the Fundamental Theorem of Algebra.";
  624.  
  625. Accented characters can also be referred to as constants, like other
  626. characters.  Just as 'x' represents the character lower-case-X, so
  627. '@^A' represents capital-A-circumflex."
  628.  
  629.           (Inform Designer's Manual, third edition (1996), section 1.14)
  630.  
  631.  
  632. As from Inform 6.10, accents can be used equally in dictionary words.
  633. This is particularly important in languages such as Finnish, where '@:a' and
  634. '@:o' are significantly different characters from 'a' and 'o':
  635.  
  636.    'vaara' means "danger"
  637.    'v@:a@:ar@:a' means "wrong"
  638.  
  639. This raises an awkward technicality.  Dictionary words are stored internally
  640. to a "resolution" of 9 Z-characters: that is, only the first 9 Z-characters
  641. are looked at, so that
  642.  
  643.    'chrysanthemum'    is stored as   'chrysanth'
  644.    'chrysanthemums'   is stored as   'chrysanth'
  645.  
  646. This is normally no problem, but unfortunately Z-characters are not the same
  647. as letters.  That is,
  648.  
  649.     letters A to Z       take up 1 Z-character each
  650.     accented letters     normally take 4 Z-characters each
  651.  
  652. and this is a serious problem:
  653.  
  654.    't@'el@'ecarte'    is stored as   't@'el'
  655.    't@'el@'ephone'    is stored as   't@'el'
  656.  
  657. (there are not even enough of the 9 Z-characters left to encode the second
  658. e-acute, let alone the 'c' or the 'p' which would distinguish the two words).
  659. Inform therefore provides a mechanism to make up to about 10 common accents
  660. cheaper to use, in that they then take only 2 Z-characters each, not 4.
  661. If this mechanism were used for '@'e',
  662.  
  663.    't@'el@'ecarte'    would be stored as   't@'el@'ecar'
  664.    't@'el@'ephone'    would be stored as   't@'el@'epho'
  665.  
  666. Declaring accented characters as "cheap" in this way is one of the first
  667. tasks of a language definition file (see L.1 below).
  668.  
  669.  
  670.    2.5  Plural dictionary words
  671.    ----------------------------
  672.  
  673. A dictionary word written in the form
  674.  
  675.    'crowns//p'
  676.  
  677. is considered to be plural.  Here, plural means "can refer to more than one
  678. Inform object": you wouldn't set this for the word 'grapes' if it referred
  679. to a single object representing a bunch of grapes, for instance.
  680.  
  681. This makes it much simpler to get plurals working.  For example,
  682.  
  683.    Class Crown with name 'crown' 'crowns//p';
  684.    Crown with name 'red';
  685.    Crown with name 'green';
  686.  
  687. which has the following useful result:
  688.  
  689.    > GET CROWN
  690.    Which do you mean, the red crown or the green crown?
  691.  
  692.    > GET CROWNS
  693.    red crown: Taken.
  694.    green crown: Taken.
  695.  
  696.  
  697.    2.6  Dealing with flexion in noun phrases using grammar tokens
  698.    --------------------------------------------------------------
  699.  
  700. Linguists use the following terms for "flexion", the ways that words change
  701. according to the words surrounding them:
  702.  
  703.     "inflection": a variable ending for a word, e.g., "a peach" but
  704.          "an apple".
  705.  
  706.     "agreement": when the inflection of one word is changed to match another
  707.          word which it goes with.  E.g. "grand maison" but "grande dame"
  708.          (French), where the inflection on "grand" agrees with the gender
  709.          of the noun it is being applied to.
  710.  
  711.     "affix": part of a word which is attached either at the beginning
  712.          ("prefix"), the end ("suffix") or somewhere in the middle ("infix")
  713.          of the ordinary word (the "stem") to indicate e.g. person or
  714.          gender of the objects attached to a verb.  The affix often
  715.          plays a part that an entirely separate word would play in English.
  716.          For instance, "donnez-lui" (French: "give to him"), where the suffix
  717.          "lui" is helpfully hyphenated, or "cogela" (Spanish: "take it"),
  718.          where there is no convenient hyphen.
  719.  
  720.     "enclitic": an affix, usually a suffix, meaning "too" or "and" in English:
  721.          e.g., "-que" (Latin), "-kin" (Finnish).
  722.  
  723.     "agglutinization": the practice of composing many affixes to a single
  724.          word, so that it may even become an entire sentence: e.g.,
  725.          "kirjoitettuasi" (Finnish: "after you had written"), and Hebrew is
  726.          also agglutinizing.
  727.  
  728. Enclitics, agglutinization and affixes will have to be undone when
  729. translating the source language into Informese, and we'll come to that later.
  730. It is also essential to define:
  731.  
  732. "Case": in many languages nouns or pronouns are written differently according
  733.     to their usage in a sentence: e.g. in German
  734.  
  735.     Case of "him"       English                    German
  736.     accusative          put the frog on him        leg den frosch auf ihn
  737.     dative              take the frog from him     nimm den frosch von ihm
  738.  
  739.     and nouns take four cases, which articles tend to agree with:
  740.  
  741.          der Russe       nominative
  742.          dem Russen      dative
  743.          des Russen      genitive
  744.          den Russen      accusative
  745.  
  746.     The extreme example is Finnish, with about 30 cases (depending on what
  747.     one calls a "case": in effect, a wide range of English prepositional
  748.     phrases like "into the water" would be written as just the noun phrase
  749.     "water" with a postpositional ending meaning "into", and which we
  750.     could think of as a case).
  751.  
  752.  
  753. The words entered into an object's "name" property should normally be
  754. accusative.  This will be fine for noun phrases parsed in grammar lines like
  755.  
  756.     Verb 'take'
  757.        * noun                       -> Take;
  758.  
  759. However, consider translating the following grammar line:
  760.  
  761.     Verb 'give'
  762.        * noun 'to' noun             -> Give;
  763.  
  764. What is really going on is
  765.  
  766.     <give-verb> <accusative object> <dative object>
  767.  
  768. where, in English, the dative case survives only in the use of the word
  769. "to".  Thus the sentence would be better understood as:
  770.  
  771.     give  the banana  to the monkey
  772.           ----------  -------------
  773.           accusative     dative
  774.  
  775. and you would probably want to rewrite the grammar line as
  776.  
  777.     Verb 'give'
  778.        * noun dativenoun            -> Give;
  779.  
  780. where "dativenoun" is some token meaning "like noun, but in the dative case".
  781. For example, the German form might be
  782.  
  783.     Verb 'gib'
  784.        * noun dativenoun            -> Give
  785.        * dativenoun noun            -> Give;
  786.  
  787. (since German does not insist that the objects come in any particular order),
  788. and then
  789.  
  790.     gib dem maedchen die blumen
  791.     gib die blumen dem maedchen
  792.  
  793. will each be understood as asking to give the flowers to the girl.
  794.  
  795.  
  796. Unfortunately Inform does not come with a token called "dativenoun" built in,
  797. so you have to write one.  This will be an example of a "general parsing
  798. routine", about which there is a great deal of documentation in the
  799. Designer's Manual.  GPRs have been enhanced since the Designer's Manual
  800. (third edition) was published, though, so here's a recap:
  801.  
  802.     A general parsing routine should look at words from the current
  803.     word (the one numbered "wn" onwards), and may match one or more
  804.     words as being understood (in which case "wn" should be left
  805.     pointing to the next word not matched), or else may "fail".
  806.  
  807.     The possible return values are:
  808.     
  809.     GPR_FAIL         Text matches nothing.
  810.     GPR_REPARSE      I've actually rewritten the text, so you'll have
  811.                      to start parsing it again from the beginning.
  812.     GPR_NUMBER       Text matches a number (which should be put in
  813.                      the variable "parsed_number").
  814.     GPR_PREPOSITION  Text is understood, so carry on parsing the line,
  815.                      but it doesn't result in a number or an object.
  816.     GPR_NOUN         Parse from where I've left "wn" as though the
  817.                      token were "noun".
  818.     GPR_HELD         Ditto for "held"...
  819.     GPR_MULTI        and so on...
  820.     GPR_MULTIHELD
  821.     GPR_MULTIEXCEPT
  822.     GPR_MULTIINSIDE
  823.     GPR_CREATURE
  824.  
  825. To demonstrate this, here is an imaginary feature of English.  Suppose that
  826. the English language has a verb called "glob" whose object must be in the
  827. dative.  For instance,
  828.  
  829.     glob to the duck
  830.  
  831. is grammatical but
  832.  
  833.     glob duck
  834.  
  835. isn't (because "duck" on its own is an accusative noun).  We can set up the
  836. verb as follows:
  837.  
  838.     Verb "glob" * dativenoun -> Glob;
  839.  
  840. and here is a simple version of "dativenoun":
  841.  
  842.     [ dativenoun w;
  843.       w = NextWord();
  844.       if (w == 'to') return GPR_NOUN;
  845.       return GPR_FAIL;
  846.     ];
  847.  
  848. (read this as: if the next word is "to", try and match a noun following
  849. it; otherwise the sentence isn't grammatical).  Now suppose further that
  850. English is inflected after all.  We shall pretend that for most nouns, one
  851. simply suffixes "ot" to the end.  But a few nouns are irregular: the
  852. dative of "gull" is by some historical accident "gullit", not "gullot".
  853. Now we have to make "dativenoun" cope with the following possibilities:
  854.  
  855.     glob duck                 incorrect
  856.     glob to the duck          correct
  857.     glob the duckot           correct
  858.     glob duckot               correct
  859.     glob to gull              correct
  860.     glob gullot               incorrect
  861.     glob gullit               correct
  862.  
  863. Here is a second try.  Suppose we create our duck and gull objects by:
  864.  
  865.     Object -> "duck"
  866.       with name 'duck',
  867.            dativename 'duckot';
  868.     Object -> "gull"
  869.       with name 'gull',
  870.            dativename 'gullit';
  871.  
  872.     [ dativenoun w;
  873.       w = NextWord();
  874.       if (w == 'to') return GPR_NOUN;
  875.       wn--;
  876.       parser_inflection = dativename;
  877.       return GPR_NOUN;
  878.     ];
  879.  
  880. "parser_inflection" is a variable used in the parser to know the case of
  881. what's being parsed.  It must always be equal to _either_ a property, _or_
  882. a routine.  Most of the time it's equal to the property "name", which
  883. just means "accusative case as normal".  If it equals another property,
  884. such as "dativename", then the parser looks in that property for name-words
  885. instead of in "name".
  886.  
  887. This now does what was asked.  But it's really an annoying burden on the
  888. game designer to expect him to give dative forms of every name, particularly
  889. if for almost every name the dative is formed by suffixing "ot".  It's for
  890. this that "parser_inflection" can be set to a routine name.  So here is yet
  891. a third form:
  892.  
  893.     Object -> "duck"
  894.       with name 'duck' 'bird' 'mallard';
  895.     Object -> "gull"
  896.       with name 'gull' 'bird',
  897.            dativename 'gullit';
  898.  
  899.     [ dative obj word a l;
  900.       a = WordAddress(wn-1);
  901.       l = WordLength(wn-1);
  902.  
  903.       if (l >= 3 && a->(l-2)=='o' or 'O' && a->(l-1)=='t' or 'T')
  904.       {   word = DictionaryLookup(a, l-2);
  905.           return WordInProperty(word, obj, name);
  906.       }
  907.  
  908.       if (obj provides dativename)
  909.           return WordInProperty(word, obj, dativename);
  910.       rfalse;
  911.     ];
  912.  
  913.     [ dativenoun w;
  914.       w = NextWord();
  915.       if (w == 'to') return GPR_NOUN;
  916.       wn--;
  917.       parser_inflection = dative;
  918.       return GPR_NOUN;
  919.     ];
  920.  
  921. An inflection routine, like "dative", is called with two arguments, an
  922. object and a dictionary word.  It has to reply true or false -- true
  923. if the dictionary word can mean the object, false if not.  "wn" is always
  924. set to the number of the next word along (and it should not be moved).
  925.  
  926. What happens in "dative" is that two standard library routines are used
  927. to find the actual text of the word being looked at.  (This will be exactly
  928. in the form the player typed -- which is convenient if the word is very
  929. long and contains a vital suffix.)  After the statements
  930.  
  931.       a = WordAddress(wn-1);
  932.       l = WordLength(wn-1);
  933.  
  934. then the word being argued over is held in the array
  935.  
  936.       a->0, a->1, ..., a->(l-1)
  937.  
  938. so we might for instance have l=6 and
  939.  
  940.       a->0 = 'd'
  941.       a->1 = 'u'
  942.       a->2 = 'c'
  943.       a->3 = 'k'
  944.       a->4 = 'o'
  945.       a->5 = 't'
  946.  
  947. The "dative" routine looks to see if the last two letters are OT, as in this
  948. case they are.  It then uses two more library routines.
  949.  
  950.     DictionaryLookup(text, length)
  951.  
  952. returns 0 if the word at "text" and of the given length is not in the game's
  953. dictionary, or its dictionary entry if it is.  In this case, the call
  954.  
  955.     DictionaryLookup(a, 4)
  956.  
  957. tests whether "duck" is in the dictionary, and it is, so the variable "word"
  958. becomes the dictionary entry 'duck'.  And "dative" finally uses another
  959. library routine,
  960.  
  961.     WordInProperty(word, object, property)
  962.  
  963. to see if this is one of the words listed in object.property.
  964.  
  965. If on the other hand the word had not ended in OT -- if it were "gullit",
  966. for instance -- then the "dative" routine would have tried to look it up
  967. in the object's "dativename" property.  Finally, then, the designer only
  968. has to give names in the dativename property if they are irregular.  The
  969. dative forms
  970.  
  971.     birdot, duckot, mallardot
  972.  
  973. are recognised automatically.  ("gullot" is also detected, though it's
  974. wrong.  But Inform's parser always takes the view that it's better to
  975. understand too much than too little.)
  976.  
  977. One more surreal invention.  Let us suppose English has the pronominal
  978. adverb "toit", meaning "to it", which can be used as a dative.  The
  979. easiest way to arrange this is to elaborate "dativenoun" again:
  980.  
  981.     [ dativenoun w;
  982.       w = NextWord();
  983.       if (w == 'to') return GPR_NOUN;
  984.       if (w == 'toit')
  985.       {   w = PronounValue('it');
  986.           if (w == NULL) return GPR_FAIL;
  987.           if (TestScope(w, actor)) return w;
  988.           return GPR_FAIL;
  989.       }
  990.       wn--;
  991.       parser_inflection = dative;
  992.       return GPR_NOUN;
  993.     ];
  994.  
  995. Note that it isn't safe to always allow "it" to be referred to --
  996. "it" might be an object in another room and now out of scope.  Or it might
  997. still be unset.  (In the case of 'it', this is unlikely.  But a pronoun
  998. meaning "a group of two or more women" might well remain unset throughout
  999. a game.)
  1000.  
  1001. Tokens like "dativenoun" are best defined in the grammar file, not the
  1002. language definition file.  (It doesn't really matter, but it's better form.)
  1003.  
  1004. Similar means can be used for languages, such as German or Swedish, in which
  1005. nouns or adjectives agree with the article (definite or indefinite) applied
  1006. to them.  For example,
  1007.  
  1008.     English              Swedish
  1009.     a brown dog          en brun hund
  1010.     the brown dog        den bruna hunden
  1011.     a brown house        ett brunt hus
  1012.     the brown house      det bruna huset
  1013.  
  1014. The simplest solution would be to make the designer always allow all forms,
  1015. e.g.,
  1016.  
  1017.     Object ->
  1018.       with name 'brun' 'bruna' 'hund' 'hunden';
  1019.     Object ->
  1020.       with name 'brunt' 'bruna' 'hus' 'huset';
  1021.  
  1022. But if it's felt that this is an unreasonable burden to place on the game
  1023. designer, a parser_inflection routine could be designed to handle it.
  1024. It may be useful to know that the variable
  1025.  
  1026.     indef_mode
  1027.  
  1028. is always set to "true" when parsing something known to be indefinite (e.g.
  1029. because an indefinite article has just been typed), and "false" otherwise.
  1030.  
  1031. Finally, note that the above methods are only one way of dealing with
  1032. case suffixes and pronominal adverbs.  You could instead handle these at the
  1033. "translating to Informese" stage, by writing code that translates
  1034.  
  1035.     glob duckot                -->     glob to duck
  1036.     glob toit                  -->     glob to it
  1037.     den bruna hunden           -->     den brun hund
  1038.     det bruna huset            -->     det brun hus
  1039.  
  1040. before parsing gets underway.  In a heavily inflected language with many
  1041. irregularities, a combination of the two techniques may be needed.
  1042.  
  1043.  
  1044.    L.0  Organisation of language definition files
  1045.    ----------------------------------------------
  1046.  
  1047. A language definition file is itself written in Inform.  (When reading this
  1048. and the other L.* sections, it may be useful to have a copy of English.h
  1049. (the English LDF) to refer to.)  Such a file is divided into four parts:
  1050.  
  1051.    Part I.   Preliminaries
  1052.    Part II.  Vocabulary
  1053.    Part III. Translating to Informese
  1054.    Part IV.  Printing
  1055.  
  1056. It would be very helpful if all LDFs could follow the order and layout style
  1057. of "English.h", and in particular follow this division into four parts.
  1058.  
  1059. The example of French will be developed throughout, with diversions to
  1060. other languages when this would be more interesting.
  1061.  
  1062.  
  1063.    L.I.1  Version number and alphabet
  1064.    ----------------------------------
  1065.  
  1066. The file should begin as follows:
  1067.  
  1068.     ! =======================================================================
  1069.     !   Inform Library Definition File: French
  1070.     !
  1071.     !   (c) Graham Nelson 1996
  1072.     ! -----------------------------------------------------------------------
  1073.     System_file;
  1074.     ! -----------------------------------------------------------------------
  1075.     !   Part I.   Preliminaries
  1076.     ! -----------------------------------------------------------------------
  1077.     Constant LanguageVersion
  1078.             = "Traduction fran@ccais 961205 par Graham Nelson";
  1079.  
  1080. [The English LDF defines a constant called EnglishNaturalLanguage here, but
  1081. this is just to help the library keep old code working with the new parser:
  1082. don't define a similar constant yourself.]
  1083.  
  1084. The next ingredient of Part I is declaring the accented letters which
  1085. are "important" (see 2.4 above).  Up to about 10 can be so given.  The
  1086. most important should be given first; if more than 10 are given, then it's
  1087. possible that those towards the bottom of the list may not find room for
  1088. themselves in the list of "cheap" letters.  The declarations should use the
  1089. "Zcharacter" directive (see the Inform Technical Manual if you're curious
  1090. about this).  For example:
  1091.  
  1092.     Zcharacter '@'e';         ! E-acute
  1093.     Zcharacter '@`e';         ! E-grave
  1094.     Zcharacter '@`a';         ! A-grave
  1095.     Zcharacter '@`u';         ! U-grave
  1096.     Zcharacter '@^a';         ! A-circumflex
  1097.     Zcharacter '@^e';         ! E-circumflex
  1098.  
  1099. (Note that since the Z-machine automatically reduces anything the player
  1100. types into lower case, we need only include lower-case accented letters here.
  1101. Note also that there are plenty of other French accented letters -- I-umlaut,
  1102. U-circumflex, etc. -- but the others are quite uncommon.)
  1103.  
  1104.  
  1105.    L.I.2   Compass objects
  1106.    -----------------------
  1107.  
  1108. All that is left in Part I is to declare standard compass directions.  The
  1109. corresponding part of "English.h" reads:
  1110.  
  1111.     Class  CompassDirection
  1112.       with article "the", number 0
  1113.       has  scenery;
  1114.     Object Compass "compass" has concealed;
  1115.     IFNDEF WITHOUT_DIRECTIONS;
  1116.     CompassDirection -> n_obj "north wall"
  1117.                         with name 'n' 'north' 'wall',      door_dir n_to;
  1118.     CompassDirection -> s_obj "south wall"
  1119.                         with name 's' 'south' 'wall',      door_dir s_to;
  1120.     CompassDirection -> e_obj "east wall"
  1121.                         with name 'e' 'east' 'wall',       door_dir e_to;
  1122.     CompassDirection -> w_obj "west wall"
  1123.                         with name 'w' 'west' 'wall',       door_dir w_to;
  1124.     CompassDirection -> ne_obj "northeast wall"
  1125.                         with name 'ne' 'northeast' 'wall', door_dir ne_to;
  1126.     CompassDirection -> nw_obj "northwest wall"
  1127.                         with name 'nw' 'northwest' 'wall', door_dir nw_to;
  1128.     CompassDirection -> se_obj "southeast wall"
  1129.                         with name 'se' 'southeast' 'wall', door_dir se_to;
  1130.     CompassDirection -> sw_obj "southwest wall"
  1131.                         with name 'sw' 'southwest' 'wall', door_dir sw_to;
  1132.     CompassDirection -> u_obj "ceiling"
  1133.                         with name 'u' 'up' 'ceiling',      door_dir u_to;
  1134.     CompassDirection -> d_obj "floor"
  1135.                         with name 'd' 'down' 'floor',      door_dir d_to;
  1136.     ENDIF;
  1137.     CompassDirection -> out_obj "outside"
  1138.                         with                               door_dir out_to;
  1139.     CompassDirection -> in_obj "inside"
  1140.                         with                               door_dir in_to;
  1141.  
  1142. and this should be copied as nearly as possible, with the dictionary words
  1143. (in single quotes above) translated.  For example, "French.h" has:
  1144.  
  1145.     Class  CompassDirection
  1146.       with article "le", number 0
  1147.       has  scenery;
  1148.     Object Compass "compas" has concealed;
  1149.     IFNDEF WITHOUT_DIRECTIONS;
  1150.     CompassDirection -> n_obj "mur nord"
  1151.                         with name 'n' 'nord' 'mur',        door_dir n_to;
  1152.     CompassDirection -> s_obj "mur sud"
  1153.                         with name 's' 'south' 'mur',       door_dir s_to;
  1154.     CompassDirection -> e_obj "mur est"
  1155.                         with name 'e' 'east' 'mur',        door_dir e_to;
  1156.     CompassDirection -> w_obj "mur ouest"
  1157.                         with name 'o' 'ouest' 'mur',       door_dir w_to;
  1158.     CompassDirection -> ne_obj "mur nord-est"
  1159.                         with name 'ne' 'nordest' 'mur',    door_dir ne_to;
  1160.     CompassDirection -> nw_obj "mur nord-ouest"
  1161.                         with name 'no' 'nordouest' 'mur',  door_dir nw_to;
  1162.     CompassDirection -> se_obj "mur sud-est"
  1163.                         with name 'se' 'sudest' 'mur',     door_dir se_to;
  1164.     CompassDirection -> sw_obj "mur sud-ouest"
  1165.                         with name 'so' 'sudouest' 'mur',   door_dir sw_to;
  1166.     CompassDirection -> u_obj "plafond"
  1167.                         with name 'h' 'haut' 'plafond',    door_dir u_to;
  1168.     CompassDirection -> d_obj "planch@'e"
  1169.                         with name 'b' 'bas' 'planche',     door_dir d_to;
  1170.     ENDIF;
  1171.     CompassDirection -> out_obj "l'ext@'erieure"
  1172.                         with                               door_dir out_to
  1173.                         has proper;
  1174.     CompassDirection -> in_obj "l'int@'erieure"
  1175.                         with                               door_dir in_to
  1176.                         has proper;
  1177.  
  1178.  
  1179.    L.II.1  Informese vocabulary: miscellaneous
  1180.    -------------------------------------------
  1181.  
  1182. Part II begins with dictionary words for various simple parts of speech.  For
  1183. instance, we are required to give three synonymous ways to write "again"
  1184. (the command meaning "repeat the previous command").  In French, this might
  1185. be:
  1186.  
  1187.     Constant AGAIN1__WD   = 'encore';
  1188.     Constant AGAIN2__WD   = #n$c;
  1189.     Constant AGAIN3__WD   = 'encore';
  1190.  
  1191. (We can't actually think of a third different word.  But we must define
  1192. AGAIN3__WD all the same, and must not allow it to be 0.)
  1193.  
  1194. gives three synonymous words for what would be called the "again" command in
  1195. English: two of these are the same.  (Do not define any as zero: if necessary,
  1196. duplicate them as above if you don't need the number provided.)  So in French
  1197. Inform, "encore" and "c" will both repeat the previous command.
  1198.  
  1199. These sets all take the form above.  There are:
  1200.  
  1201.     AGAIN*__WD      words meaning the "again" command
  1202.     UNDO*__WD       words meaning the "undo" command
  1203.     OOPS*__WD       words meaning the "oops" command
  1204.  
  1205.     THEN*__WD       then-words
  1206.     AND*__WD        connective: conjunction
  1207.     BUT*__WD        connective: disjunction
  1208.     ALL*__WD        all-words
  1209.     OTHER*__WD      other-words
  1210.     ME*__WD         me-words
  1211.     OF*__WD         words like "of" used in the sense of "three of the boxes"
  1212.                     when parsing a reference to a given number of things
  1213.  
  1214.     YES*__WD        words meaning "yes" when answering "yes or no" questions
  1215.     NO*__WD         words meaning "no" when answering "yes or no" questions
  1216.  
  1217. In each case * runs from 1 to 3, except for ALL where it runs 1 to 5 and OF
  1218. where it runs from 1 to 4.
  1219.  
  1220. Note that French provides the single-letter word "o" as an answer to yes-no
  1221. questions (oui-non questions in French), which doesn't clash with the direction
  1222. abbreviation "o" for "ouest" since these yes-no words are used only to parse
  1223. answers to direct questions, not in general parsing.  So we could have
  1224.  
  1225.     Constant YES1__WD     = #n$o;
  1226.     Constant YES2__WD     = 'oui';
  1227.     Constant YES3__WD     = 'oui';
  1228.  
  1229. (Likewise "n" for "non", even though "n" is also "nord" in more general play.)
  1230.  
  1231. After the above, a few words have to be defined as possible replies to the
  1232. question asked when the game ends.  Here the French example is:
  1233.  
  1234.     Constant AMUSING__WD  = 'amusant';
  1235.     Constant FULLSCORE1__WD = 'grandscore';
  1236.     Constant FULLSCORE2__WD = 'grand';
  1237.     Constant QUIT1__WD    = #n$a;
  1238.     Constant QUIT2__WD    = 'arret';
  1239.     Constant RESTART__WD  = 'restart';
  1240.     Constant RESTORE__WD  = 'restore';
  1241.  
  1242.  
  1243.    L.II.2  Informese vocabulary: pronouns
  1244.    --------------------------------------
  1245.  
  1246. Part II continues with a table of pronouns, and this is perhaps best explained
  1247. by example.  Here is the table from "English.h":
  1248.  
  1249.     Array LanguagePronouns table
  1250.    
  1251.       !  word       possible GNAs                   connected
  1252.       !             to follow:                      to:
  1253.       !             a     i
  1254.       !             s  p  s  p
  1255.       !             mfnmfnmfnmfn                 
  1256.    
  1257.          'it'     $$001000111000                    NULL
  1258.          'him'    $$100000000000                    NULL
  1259.          'her'    $$010000000000                    NULL
  1260.          'them'   $$000111000111                    NULL;
  1261.  
  1262. The "connected to" column should always be created with NULL entries.
  1263. The pattern of 1s and 0s in the middle column indicates which types of
  1264. name might be referred to with the given pronoun.  For instance, "it"
  1265. might refer to any singular noun which is not the name of a man, woman
  1266. or higher animal.  (In the table, I've said that "it" also covers
  1267. inanimate singular male and female GNAs -- actually these GNAs should
  1268. never arise in English anyway.)  Whereas "her" can only stand for a single
  1269. female name.
  1270.  
  1271. English has an unusually simple pronoun structure, because accusative and
  1272. dative pronouns are identical.  French is richer, in that one set of pronouns
  1273. are used to stand for direct objects:
  1274.  
  1275.     donne-le-lui             give it to him/her
  1276.  
  1277. and another, different set are "disjunctive" pronouns (disjunctive meaning
  1278. in this context that they stand apart from the verb, and are not hyphenated
  1279. to it):
  1280.  
  1281.     mange avec lui           eat with him
  1282.  
  1283. And here goes:
  1284.  
  1285.     Array LanguagePronouns table
  1286.  
  1287.       !  word       possible GNAs                   connected
  1288.       !             to follow:                      to:
  1289.       !             a     i
  1290.       !             s  p  s  p
  1291.       !             mfnmfnmfnmfn                 
  1292.  
  1293.          !   Object pronouns
  1294.  
  1295.          '-le'    $$100000100000                    NULL
  1296.          '-la'    $$010000010000                    NULL
  1297.          '-les'   $$000110000110                    NULL
  1298.          '-lui'   $$110000110000                    NULL
  1299.          '-leur'  $$000110000110                    NULL
  1300.  
  1301.          !   Disjunctive pronouns
  1302.  
  1303.          'lui'    $$100000100000                    NULL
  1304.          'elle'   $$010000010000                    NULL
  1305.          'eux'    $$000100000100                    NULL
  1306.          'elles'  $$000010000010                    NULL;
  1307.  
  1308. [As we shall see in L.III.1, the hyphenation leaves us some work to do
  1309. when translating the player's input into Informese -- we want hyphenated
  1310. words to be split up in order for the above to work.]
  1311.  
  1312. Using the "pronouns" verb in a game will print out current values, which
  1313. may be useful when debugging the above table.
  1314.  
  1315. A game can find the current value of a pronoun by calling, e.g.,
  1316.  
  1317.    PronounValue('him')
  1318.  
  1319. which returns either NULL (if "him" is unset) or the object number it refers
  1320. to.  More usefully, a game can announce that an object has been mentioned
  1321. by calling
  1322.  
  1323.    PronounNotice(object)
  1324.  
  1325. For instance, if a magic lantern should suddenly appear, the piece of code
  1326. making it appear should call PronounNotice(magic_lantern).  The parser will
  1327. then make 'it' (or whatever pronouns apply) refer to the lantern.  This
  1328. replaces the old way of doing things, which was to set the variable
  1329.  
  1330.    itobj = magic_lantern
  1331.  
  1332. (itobj, himobj and herobj are still supported in the English version of the
  1333. parser only, to make sure old code still works).
  1334.  
  1335.  
  1336.    L.II.3  Informese vocabulary: descriptors
  1337.    -----------------------------------------
  1338.  
  1339. Part II continues with a table of descriptors, in a similar format.
  1340.  
  1341.     Array LanguageDescriptors table
  1342.    
  1343.       !  word       possible GNAs   descriptor      connected
  1344.       !             to follow:      type:           to:
  1345.       !             a     i
  1346.       !             s  p  s  p
  1347.       !             mfnmfnmfnmfn                 
  1348.  
  1349.          'my'     $$111111111111    POSSESS_PK      0
  1350.          'this'   $$111000111000    POSSESS_PK      0
  1351.          'these'  $$000111000111    POSSESS_PK      0
  1352.          'his'    $$111111111111    POSSESS_PK      'him'
  1353.          'her'    $$111111111111    POSSESS_PK      'her'
  1354.          'their'  $$111111111111    POSSESS_PK      'them'
  1355.          'its'    $$111111111111    POSSESS_PK      'it'
  1356.          'the'    $$111111111111    DEFART_PK       NULL
  1357.          #n$a     $$111000111000    INDEFART_PK     NULL
  1358.          'an'     $$111000111000    INDEFART_PK     NULL
  1359.          'some'   $$000111000111    INDEFART_PK     NULL;
  1360.  
  1361. This gives three of the four types of descriptor:
  1362.  
  1363.    POSSESS_PK     A possessive adjective, connected either to 0
  1364.                   (meaning to the player object) or to the object
  1365.                   referred to by the given pronoun -- which must be one
  1366.                   of those in the pronoun table.
  1367.  
  1368.    DEFART_PK      A definite article.  The connected-to value should be
  1369.                   NULL.
  1370.  
  1371.    INDEFART_PK    An indefinite article.  The connected-to value should be
  1372.                   NULL.
  1373.  
  1374. The fourth kind allows extra descriptors to be added which force the objects
  1375. that follow to have (or not to have) a given attribute.  For example, the
  1376. following three lines would implement "lit", "lighted" and "unlit" as
  1377. adjectives automatically understood by the English parser:
  1378.  
  1379.          'lit'    $$111111111111    light           NULL
  1380.         'lighted' $$111111111111    light           NULL
  1381.          'unlit'  $$111111111111    (-light)        NULL
  1382.  
  1383. An attribute name means "must have this attribute"; the negation of it
  1384. means "must not have this attribute".
  1385.  
  1386. To continue the example, "French.h" has descriptors table:
  1387.  
  1388.     Array LanguageDescriptors table
  1389.  
  1390.       !  word       possible GNAs   descriptor      connected
  1391.       !             to follow:      type:           to:
  1392.       !             a     i
  1393.       !             s  p  s  p
  1394.       !             mfnmfnmfnmfn                 
  1395.  
  1396.          'le'     $$100000100000    DEFART_PK       NULL
  1397.          'la'     $$010000010000    DEFART_PK       NULL
  1398.          'l^'     $$110000110000    DEFART_PK       NULL
  1399.          'les'    $$000110000110    DEFART_PK       NULL
  1400.          'un'     $$100000100000    INDEFART_PK     NULL
  1401.          'une'    $$010000010000    INDEFART_PK     NULL
  1402.          'des'    $$000110000110    INDEFART_PK     NULL
  1403.    
  1404.          'mon'    $$100000100000    POSSESS_PK      0
  1405.          'ma'     $$010000010000    POSSESS_PK      0
  1406.          'mes'    $$000110000110    POSSESS_PK      0
  1407.          'son'    $$100000100000    POSSESS_PK      '-lui'
  1408.          'sa'     $$010000010000    POSSESS_PK      '-lui'
  1409.          'ses'    $$000110000110    POSSESS_PK      '-lui'
  1410.          'leur'   $$110000110000    POSSESS_PK      '-les'
  1411.          'leurs'  $$000110000110    POSSESS_PK      '-les';
  1412.  
  1413. (recall that in dictionary words, the apostrophe is written ^, so that
  1414. 'l^' means "l'").  Thus, "son oiseau" means "his bird" or "her bird"
  1415. according to what "-lui" would currently mean (i.e., the most recent singular
  1416. noun referred to).
  1417.  
  1418. Note that in the French tables, the ambiguity of (say) "leur" (does it mean
  1419. the possessive adjective for the last plural mentioned, or does it mean the
  1420. plural direct object pronoun?) is resolved by the hyphen trick: we're
  1421. distinguishing between "-leur" (direct object pronoun) and "leur" (possessive
  1422. adjective), just as we distinguished between "-lui" (direct object pronoun)
  1423. and "lui" (disjunctive pronoun).
  1424.  
  1425. It is not always so easy.  In English, "her" can mean either the possessive
  1426. adjective for a feminine singular, or the object pronoun for a feminine
  1427. singular, so that it occurs in both pronoun and descriptor tables.  The
  1428. Inform parser notices this automatically and tries out both meanings when
  1429. parsing.
  1430.  
  1431.  
  1432.    L.II.4  Informese vocabulary: numbers
  1433.    -------------------------------------
  1434.  
  1435. An array should be given of dictionary words for the first 20 numbers, e.g.:
  1436.  
  1437.     Array LanguageNumbers table
  1438.         'un' 1 'une' 1 'deux' 2 'trois' 3 'quatre' 4 'cinq' 5
  1439.         'six' 6 'sept' 7 'huit' 8 'neuf' 9 'dix' 10
  1440.         'onze' 11 'douze' 12 'treize' 13 'quatorze' 14 'quinze' 15
  1441.         'seize' 16 'dix-sept' 17 'dix-huit' 18 'dix-neuf' 19 'vingt' 20;
  1442.  
  1443. [In some languages, like Russian, there are numbers larger than 1 which
  1444. inflect with gender: please recognise all possibilities here.]
  1445.  
  1446.  
  1447.    L.III.1  Translating natural language to Informese
  1448.    --------------------------------------------------
  1449.  
  1450. Part III is potentially the trickiest part of a language definition file
  1451. to write: it holds the routine to convert what the player has typed into
  1452. Informese.  This is optional, but for most languages something will have
  1453. to be done.  For instance:
  1454.  
  1455.   *  Break up words at hyphens and apostrophes. (The Z-machine doesn't
  1456.      automatically do this.)  Thus
  1457.  
  1458.          donne-lui l'oiseau  (French: "give him the bird")
  1459.  
  1460.      is transformed into
  1461.  
  1462.          donne -lui l' oiseau
  1463.  
  1464.   *  Remove inflections which don't carry useful information.  For
  1465.      instance, most German imperatives can take two forms, one with an
  1466.      "e" on the end:
  1467.  
  1468.          leg = lege (German: "put")    schau = schaue (German: "look")
  1469.  
  1470.      It would be helpful to remove the "e", which would avoid stuffing
  1471.      game dictionaries full of essentially duplicate entries.
  1472.  
  1473.   *  Break affixes away from the words they're glued to.  For instance,
  1474.  
  1475.          cogela (Spanish: "take it")
  1476.  
  1477.      transformed into
  1478.  
  1479.          coge la
  1480.  
  1481.      so that the affix part "la" becomes a separate word and can be treated
  1482.      as a pronoun.
  1483.  
  1484.   *  Rewrite words which contain more than one kind of Informese grammar.
  1485.      This one way (though not the only way) to handle pronominal adverbs.
  1486.      For instance (French):
  1487.      
  1488.          dessus   -->   sur lui
  1489.          dedans   -->   dans lui
  1490.  
  1491.      German has a systematic rule for such words:
  1492.  
  1493.          davon    -->   von es
  1494.          darauf   -->   auf es
  1495.  
  1496.      (Any German preposition can have "da" or "dar" applied this way.)
  1497.      This clearly has to be done with some care.  We wouldn't want to
  1498.      transform
  1499.      
  1500.          Darren   -->   rren es
  1501.  
  1502.   *  Alter word order.  For instance, if the verb occurs at the end of
  1503.      an imperative verb phrase, move it to the start.  Or consider
  1504.      Norwegian, in which (although the indefinite article is straightforward)
  1505.      the definite article is suffixed to nouns:
  1506.  
  1507.          kakane (Norwegian: "the cakes")  -->  ne kake
  1508.  
  1509. Part III of the language definition file, then, must consist of one routine,
  1510. called "LanguageToInformese" (and may also contain any other routines or
  1511. arrays you need to get this routine working).  Informese being modelled on
  1512. English, and English being simple anyway, the "English.h" just has:
  1513.  
  1514.     [ LanguageToInformese;
  1515.     ];
  1516.  
  1517. To write something more substantial you need to know how the Inform parser
  1518. stores text.  When the call to LanguageToInformese is made, the text that
  1519. the player typed is held in a -> array called "buffer", and some useful
  1520. information about it is held in another array called "parse".
  1521.  
  1522.    buffer->0  is the maximum number of characters ever allowed
  1523.    buffer->1  is the number actually typed
  1524.    buffer->2  ...and subsequent entries... contain the characters.
  1525.  
  1526. For instance, the contents might look something like this:
  1527.  
  1528.    buffer-> 0   1   2   3   4   5   6   7   8   9  10  11  ...
  1529.             80  8   t   a   k   e       a   l   l  ...........
  1530.  
  1531. The useful information in "parse" is as follows:
  1532.  
  1533.    parse->0   is the maximum number of words ever allowed
  1534.    parse->1   is the number actually typed
  1535.  
  1536.    parse-->(x*2+1)  is the dictionary entry for word x (counting from 0),
  1537.                     or 0 if it's not in the game's dictionary
  1538.  
  1539.    parse->(x*4+4)   is the number of characters of text word x takes up
  1540.    parse->(x*4+5)   is the position of the first character of word x in
  1541.                     the buffer.
  1542.  
  1543. For instance, the contents might look like this:
  1544.  
  1545.    parse->  0   1          4   5        8   9   ...............
  1546.    parse-->         1              3            ...............
  1547.  
  1548.             20  2          4   2        3   7   ...............
  1549.                     'take'         'all'        ...............
  1550.  
  1551. The translation process has to be done by shifting characters about and
  1552. altering them in "buffer".  Of course, the moment anything in "buffer" is
  1553. changed, the information in "parse" becomes out of date.  But you can
  1554. bring it back up to date with the (Inform assembly-language) statement
  1555.  
  1556.     @tokenise buffer parse;
  1557.  
  1558. (Indeed, the parser does just this when the LanguageToInformese routine
  1559. has finished.)
  1560.  
  1561.  
  1562. (a) First example: French hyphens and apostrophes
  1563.  
  1564. Here is the translation required to handle French hyphens and apostrophes
  1565. as in the description above:
  1566.  
  1567.     [ LanguageToInformese x;
  1568.  
  1569.       !   Insert a space before each hyphen and after each apostrophe.
  1570.  
  1571.       for (x=2:x<2+buffer->1:x++)
  1572.       {   if (buffer->x == '-') LTI_Insert(x++, ' ');
  1573.           if (buffer->x == ''') LTI_Insert(x+1, ' ');
  1574.       }
  1575.  
  1576.       !   This code would print out the modified text, for testing purposes,
  1577.       !   if it were not commented out:
  1578.       !
  1579.       !   print "[";
  1580.       !   for (x=2:x<2+buffer->1:x++)
  1581.       !       print (char) buffer->x;
  1582.       !   print "]^";
  1583.     ];
  1584.    
  1585. Note that
  1586.  
  1587.       for (x=2:x<2+buffer->1:x++)
  1588.  
  1589. loops through the characters of text in the buffer, and LTI_Insert is a
  1590. library routine provided to help with translations:
  1591.  
  1592.     LTI_Insert(position, character)
  1593.  
  1594. inserts the given character at buffer->position, moving all the subsequent
  1595. characters along by one.  (It's automatically protected from letting the
  1596. text overflow out of the buffer.)  Deleting characters is usually unnecessary:
  1597. you can simply over-write them with spaces.
  1598.  
  1599.  
  1600. (b) Second example: French words "dessus" and "dedans"
  1601.  
  1602. Here is code to replace any usage of "dessus" by "sur lui" and of "dedans"
  1603. by "dans lui":
  1604.  
  1605.      for (x=0:x<parse->1:x++)
  1606.      {
  1607.          word = parse-->(x*2 + 1);
  1608.          at = parse->(x*4 + 5);
  1609.    
  1610.          if (word == 'dessus')
  1611.          {   LTI_Insert(at, ' ');
  1612.              buffer->at     = 's';
  1613.              buffer->(at+1) = 'u';
  1614.              buffer->(at+2) = 'r';
  1615.              buffer->(at+3) = ' ';
  1616.              buffer->(at+4) = 'l';
  1617.              buffer->(at+5) = 'u';
  1618.              buffer->(at+6) = 'i';
  1619.              break;
  1620.          }
  1621.          if (word == 'dedans')
  1622.          {   LTI_Insert(at, ' ');          
  1623.              LTI_Insert(at, ' ');          
  1624.              buffer->at     = 'd';
  1625.              buffer->(at+1) = 'a';
  1626.              buffer->(at+2) = 'n';
  1627.              buffer->(at+3) = 's';
  1628.              buffer->(at+4) = ' ';
  1629.              buffer->(at+5) = 'l';
  1630.              buffer->(at+6) = 'u';
  1631.              buffer->(at+7) = 'i';
  1632.              break;
  1633.          }
  1634.      }
  1635.  
  1636. Actually, this routine only replaces the first usage of either word in
  1637. the text, which is good enough.  We could have made it replace absolutely
  1638. every usage by writing
  1639.  
  1640.              @tokenise buffer parse;
  1641.              x = 0; continue;
  1642.  
  1643. instead of 
  1644.  
  1645.              break;
  1646.  
  1647. in the two places where that line occurs.
  1648.  
  1649.  
  1650. (c) Third example: German "da" + preposition
  1651.  
  1652.     [ LanguageToInformese x c word at len;
  1653.  
  1654.       for (x=0:x<parse->1:x++)
  1655.       {
  1656.          word = parse-->(x*2 + 1);
  1657.          len = parse->(x*4 + 4);
  1658.          at = parse->(x*4 + 5);
  1659.    
  1660.          if (word == 0 && buffer->at == 'd' && buffer->(at+1) == 'a')
  1661.          {   c=2; if (buffer->(at+2) == 'r') c=3;
  1662.              !   Is the rest of the word, after "da" or "dar", in dict?
  1663.              word = DictionaryLookup(buffer+at+c, len-c);
  1664.              if (word ~= 0)
  1665.              {   buffer->at = ' '; buffer->(at+1) = ' ';
  1666.                  if (c=3) buffer->(at+2) = ' ';
  1667.                  LTI_Insert(at+len, 's');
  1668.                  LTI_Insert(at+len, 'e');
  1669.                  LTI_Insert(at+len, ' ');
  1670.                  break;
  1671.              }
  1672.          }
  1673.       }
  1674.     ];
  1675.  
  1676. [This routine attacks "da" or "dar" plus any valid dictionary word,
  1677. as long as the whole thing isn't a valid dictionary word already.  That
  1678. might be a bit extreme -- we could impose further restrictions if we wanted
  1679. to.]
  1680.  
  1681.  
  1682.    3   Teaching Inform to write your language
  1683.    ------------------------------------------
  1684.  
  1685.    3.1  The GNA of short names
  1686.    ---------------------------
  1687.  
  1688. As explained in Section 2.3 above, Inform provides for up to three genders,
  1689. and you as the translator will have to decide how to use them.  Although
  1690. internally they are called
  1691.  
  1692.    male
  1693.    female
  1694.    neuter
  1695.  
  1696. you do not need to make "male" correspond to "masculine", and so on.  Here
  1697. are examples:
  1698.  
  1699. English: all nouns are neuter except for those of people (and sometimes
  1700.     higher animals), when they follow the gender of the person.
  1701.     
  1702. French, Spanish, Italian: nouns are masculine or feminine, but there is no
  1703.     neuter.
  1704.  
  1705. German, Dutch: nouns are masculine, feminine or neuter.
  1706.  
  1707. Norwegian: here the number of genders is a matter of dialect; an old-fashioned
  1708.     view of Norwegian is that it has two genders, "common" (containing all
  1709.     words from the older masculine and feminine genders) and "neuter": but
  1710.     nowadays Norwegian has absorbed a new feminine gender from its rural
  1711.     dialects.  So: use the "male" attribute for common gender, the "female"
  1712.     attribute for the dialect feminine and "neuter" for neuter.
  1713.  
  1714. The Inform library needs to know the GNA of object names so that it can
  1715. print articles.  For example, to print the room description:
  1716.  
  1717.     Volière
  1718.     Un jungle superb des bêtes et des arbres.
  1719.  
  1720.     On peut voir trois oiseaux (une oie, un moineau et un cygne blanc),
  1721.     cinq boîtes, un huître, Edith Piaf et des raisins ici.
  1722.  
  1723. the library needs to know that
  1724.  
  1725.     oie            is female singular
  1726.     moineau        is male singular
  1727.     cygne blanc    is male singular
  1728.     huître         is male singular
  1729.     raisins        is plural
  1730.  
  1731. It can only be sure of finding such information if it has the GNA of
  1732. every object name available.
  1733.  
  1734. A game designer using your translation of the library will have to
  1735. specify the GNA of every object's name, for printing purposes.  The A part
  1736. is easy: objects which have the
  1737.  
  1738.     animate
  1739.  
  1740. attribute have animation, and all other objects haven't.  The N part is
  1741. similar: any object which has the
  1742.  
  1743.     pluralname
  1744.  
  1745. attribute is considered to have a plural name (it's still only one object:
  1746. an example might be an object called "doors" which represented doubled
  1747. doors, or "grapes" representing a bunch of grapes).  All other objects are
  1748. considered to have singular short names.
  1749.  
  1750. To specify the gender, you can either give an object one of the attributes
  1751.  
  1752.     male
  1753.     female
  1754.     neuter
  1755.  
  1756. or you can let the Inform library guess.  It guesses using two constants,
  1757.  
  1758.     LanguageAnimateGender          default gender for something animate
  1759.     LanguageInanimateGender        default gender for something inanimate
  1760.  
  1761. which must be defined at the start of Part IV of the language definition file
  1762. (see L.IV.1).
  1763.  
  1764. Finally, there might be times when it's useful to know an object's GNA,
  1765. and for this the routine
  1766.  
  1767.    GetGNAOfObject(obj)
  1768.  
  1769. returns 0 to 11 according to the table of values given in section 2.3 above.
  1770.  
  1771.  
  1772.    3.2  Flexion in short names
  1773.    ---------------------------
  1774.  
  1775. Short names of objects are likely to vary with case, in inflected
  1776. languages such as German or Latin.  There is no automatic way Inform can
  1777. correct the case of short names, though, so it will be up to you to manage
  1778. this.  You may want to define printing rules:
  1779.  
  1780.    [ DativeName;
  1781.      ...
  1782.    ];
  1783.  
  1784.    "You give ", (name) noun, " to ", (DativeName) second;
  1785.  
  1786. It might be necessary to insist that designers always create objects with
  1787. a property giving dative forms of their short names, perhaps.
  1788.  
  1789. Inform already does this in the case of short names being inflected
  1790. according to whether they take the definite or indefinite articles.
  1791. For instance,
  1792.  
  1793.     English              Swedish
  1794.     a brown dog          en brun hund
  1795.     the brown dog        den bruna hunden
  1796.     a brown house        ett brunt hus
  1797.     the brown house      det bruna huset
  1798.  
  1799.     English              German
  1800.     the red book         das rote Buch
  1801.     a red book           ein rotes Buch
  1802.  
  1803. When a short name is being printed, the variable
  1804.  
  1805.     indef_mode
  1806.  
  1807. is always "true" if an indefinite article has just been printed, and
  1808. "false" otherwise.  So one way to provide the above would be to define
  1809.  
  1810.     Object ->
  1811.       with short_name
  1812.            [;  if (indef_mode) print "rotes Buch";
  1813.                else print "rote Buch";
  1814.                rtrue;
  1815.            ];
  1816.  
  1817. But this clumsy, so in addition to this, Inform allows you to use the
  1818. property short_name_indef:
  1819.  
  1820.     Object ->
  1821.       with short_name "rote Buch",
  1822.            short_name_indef "rotes Buch";
  1823.  
  1824.  
  1825.    L.IV.1  Default genders and contraction forms
  1826.    ---------------------------------------------
  1827.  
  1828. Part IV opens with these two declarations.  For instance, "English.h" has:
  1829.  
  1830.     Constant LanguageAnimateGender   = male;
  1831.     Constant LanguageInanimateGender = neuter;
  1832.  
  1833. whereas "French.h" has:
  1834.  
  1835.     Constant LanguageAnimateGender   = male;
  1836.     Constant LanguageInanimateGender = male;
  1837.  
  1838. Another piece of jargon: a "contraction form" is a textual feature of a
  1839. noun which causes any article in front of it to inflect.  English has two
  1840. contraction forms, "starting with a vowel" and "starting with a consonant",
  1841. and the indefinite article inflects with it:
  1842.  
  1843.     a + orange = an orange
  1844.     a + banana = a banana
  1845.  
  1846. This section must first define a constant.  In the case of "French.h":
  1847.  
  1848.     Constant LanguageContractionForms = 2;        ! French has two:
  1849.                                                   ! 0 = starting with a const.
  1850.                                                   ! 1 = starting with a vowel
  1851.                                                   !     or mute h
  1852.  
  1853. It's up to you how you number these, but contraction form 0 should be the
  1854. one which most often happens.
  1855.  
  1856. You also have to provide a routine to decide what contraction form a piece
  1857. of text has.  Here is an approximate version for French:
  1858.  
  1859.    [ LanguageContraction text;
  1860.      if (text->0 == 'a' or 'e' or 'i' or 'o' or 'u' or 'h'
  1861.                     or 'A' or 'E' or 'I' or 'O' or 'U' or 'H') return 1;
  1862.      return 0;
  1863.    ];
  1864.  
  1865. The "text" array holds the full text of the noun, though this routine would
  1866. normally only look at the first few letters at most.  (Inform only calls
  1867. this routine when it absolutely needs to know -- for instance, it doesn't
  1868. bother when printing definite articles in English, because they don't vary
  1869. with contraction form.  It detects this automatically from the table below.)
  1870.  
  1871. The above is only approximate because French has many accented vowels to
  1872. check, too.  Now a comparison going on and on like
  1873.  
  1874.                     ... or '@`e' or '@`a' or ...
  1875.  
  1876. could become very long and tiresome: you might instead want to create an
  1877. array recording whether each character is a vowel or consonant.
  1878.  
  1879.  
  1880.    L.IV.2  How to print: articles
  1881.    ------------------------------
  1882.  
  1883. The Inform library needs to print three kinds of article:
  1884.  
  1885.                                         English         French
  1886.     indefinite articles                 a, an, some     un, une, des
  1887.     definite articles                   the             le, la, l', les
  1888.     Capitalised definite articles       The             Le, La, L', les
  1889.  
  1890. Articles vary not only with contraction form but with the GNA of the noun
  1891. they apply to.
  1892.  
  1893. (a) Example 1: French
  1894.  
  1895.     Constant LanguageContractionForms = 2;        ! French has two:
  1896.                                                   ! 0 = starting with a const.
  1897.                                                   ! 1 = starting with a vowel
  1898.                                                   !     or mute h
  1899.  
  1900.     [ LanguageContraction text;
  1901.       if (text->0 == 'a' or 'e' or 'i' or 'o' or 'u' or 'h'
  1902.                      or 'A' or 'E' or 'I' or 'O' or 'U' or 'H') return 1;
  1903.       return 0;
  1904.     ];
  1905.  
  1906.     Array LanguageArticles -->
  1907.  
  1908.      !   Contraction form 0:     Contraction form 1:
  1909.      !   Cdef   Def    Indef     Cdef   Def    Indef
  1910.  
  1911.          "Le "  "le "  "un "     "L'"   "l'"   "un "         ! 0: masc sing
  1912.          "La "  "la "  "une "    "L'"   "l'"   "une "        ! 1: fem sing
  1913.          "Les " "les " "des "    "Les " "les " "des ";       ! 2: plural
  1914.  
  1915.                        !             a           i
  1916.                        !             s     p     s     p
  1917.                        !             m f n m f n m f n m f n                 
  1918.  
  1919.     Array LanguageGNAsToArticles --> 0 1 0 2 2 2 0 1 0 2 2 2;
  1920.  
  1921. Thus the array "LanguageGNAsToArticles" says, for instance, that animate
  1922. feminine plural nouns take article form 2, i.e., the third line in the
  1923. LanguageArticles array:
  1924.  
  1925.          "Les " "les " "des "    "Les " "les " "des "
  1926.  
  1927. This gives CDef, Def and Indef articles for each of contraction forms 0 and 1.
  1928.  
  1929. Note the spaces after some words in the array and not others: so, "les arbres"
  1930. but "l'huitre", for instance.
  1931.  
  1932.  
  1933. (b) Example 2: English
  1934.  
  1935.     Constant LanguageContractionForms = 2;     ! English has two:
  1936.                                                ! 0 = starting with a consonant
  1937.                                                ! 1 = starting with a vowel
  1938.  
  1939.     [ LanguageContraction text;
  1940.       if (text->0 == 'a' or 'e' or 'i' or 'o' or 'u'
  1941.                      or 'A' or 'E' or 'I' or 'O' or 'U') return 1;
  1942.       return 0;
  1943.     ];
  1944.  
  1945.     Array LanguageArticles -->
  1946.  
  1947.      !   Contraction form 0:     Contraction form 1:
  1948.      !   Cdef   Def    Indef     Cdef   Def    Indef
  1949.  
  1950.          "The " "the " "a "      "The " "the " "an "          ! Articles 0
  1951.          "The " "the " "some "   "The " "the " "some ";       ! Articles 1
  1952.  
  1953.                        !             a           i
  1954.                        !             s     p     s     p
  1955.                        !             m f n m f n m f n m f n                 
  1956.  
  1957.     Array LanguageGNAsToArticles --> 0 0 0 1 1 1 0 0 0 1 1 1;
  1958.  
  1959.  
  1960. (c) Example 3: Italian
  1961.  
  1962.    Constant LanguageContractionForms = 3;        ! 0 = starting with a const
  1963.                                                  ! 1 = starting with z
  1964.                                                  !     or s + a consonant
  1965.                                                  ! 2 = starting with a vowel
  1966.  
  1967.    [ LanguageContraction text;
  1968.      if (text->0 == 'a' or 'e' or 'i' or 'o' or 'u'
  1969.                     or 'A' or 'E' or 'I' or 'O' or 'U') return 2;
  1970.      if (text->0 == 'z') return 1;
  1971.      if (text->0 ~= 's') return 0;
  1972.      if (text->1 == 'a' or 'e' or 'i' or 'o' or 'u'
  1973.                     or 'A' or 'E' or 'I' or 'O' or 'U') return 1;
  1974.      return 0;
  1975.    ];
  1976.  
  1977.     Array LanguageArticles -->
  1978.  
  1979.      !   Contraction form 0:     Contraction form 1:     Contraction form 2:
  1980.      !   Cdef   Def    Indef     Cdef   Def    Indef     Cdef   Def    Indef
  1981.  
  1982.          "Il "  "il "  "un "     "Lo "  "lo "  "uno "    "L'"   "l'"   "un "
  1983.          "La "  "la "  "una "    "Lo "  "lo "  "una "    "L'"   "l'"   "un'"
  1984.  
  1985.          "I "   "i "   "un "     "Gli " "gli " "uno "    "Gli " "gli " "un "
  1986.          "Le "  "le "  "una "    "Gli " "gli " "una "    "Le "  "le "  "un'";
  1987.  
  1988.                        !             a           i
  1989.                        !             s     p     s     p
  1990.                        !             m f n m f n m f n m f n                 
  1991.  
  1992.     Array LanguageGNAsToArticles --> 0 1 0 2 3 0 0 1 0 2 3 0;
  1993.  
  1994.  
  1995. To complicate matters further, a few nouns have irregular articles: in
  1996. French, for instance, the initial "h" of some words is not considered mute,
  1997. for historical reasons: thus, "le haricot", not "l'haricot".  For such nouns,
  1998. the property "articles" is provided:
  1999.  
  2000.    articles "Le " "le " "un "
  2001.  
  2002. would give CDef, Def and Indef for the "haricot", overriding the system
  2003. above.
  2004.  
  2005.  
  2006.    L.IV.3  How to print: direction names
  2007.    -------------------------------------
  2008.  
  2009. Next is a routine called "LanguageDirection" to print names for direction
  2010. properties.  Imitate the following (from "French.h"):
  2011.  
  2012.     [ LanguageDirection d;
  2013.       switch(d)
  2014.       {   n_to:    print "nord";
  2015.           s_to:    print "sud";
  2016.           e_to:    print "est";
  2017.           w_to:    print "ouest";
  2018.           ne_to:   print "nordest";
  2019.           nw_to:   print "nordouest";
  2020.           se_to:   print "sudest";
  2021.           sw_to:   print "sudouest";
  2022.           u_to:    print "haut";
  2023.           d_to:    print "bas";
  2024.           in_to:   print "dans";
  2025.           out_to:  print "dehors";
  2026.           default: return RunTimeError(9,d);
  2027.       }
  2028.     ];
  2029.  
  2030.  
  2031.    L.IV.4  How to print: numbers
  2032.    -----------------------------
  2033.  
  2034. Next is a routine called "LanguageNumber" which takes a number N and prints
  2035. it out in textual form.
  2036.  
  2037. N can be anything from -32768 to +32767 and the correct text should be printed
  2038. in all cases.  This is probably easiest with a recursive algorithm.  Here,
  2039. for example, is the "French.h" version:
  2040.  
  2041.     [ LanguageNumber n f;
  2042.       if (n==0)    { print "z@'ero"; rfalse; }
  2043.       if (n<0)     { print "moins "; n=-n; }
  2044.       if (n>=1000) { print (LanguageNumber) n/1000, " mille"; n=n%1000; f=1; }
  2045.       if (n>=100)  { if (f==1) print ", ";
  2046.                      print (LanguageNumber) n/100, " cent"; n=n%100; f=1; }
  2047.       if (n==0) rfalse;
  2048.       switch(n)
  2049.       {   1:  print "un";
  2050.           2:  print "deux";
  2051.           3:  print "trois";
  2052.           4:  print "quatre";
  2053.           5:  print "cinq";
  2054.           6:  print "six";
  2055.           7:  print "sept";
  2056.           8:  print "huit";
  2057.           9:  print "neuf";
  2058.           10: print "dix";
  2059.           11: print "onze";
  2060.           12: print "douze";
  2061.           13: print "treize";
  2062.           14: print "quatorze";
  2063.           15: print "quinze";
  2064.           16: print "seize";
  2065.           17: print "dix-sept";
  2066.           18: print "dix-huit";
  2067.           19: print "dix-neuf";
  2068.           20 to 99:
  2069.               switch(n/10)
  2070.               {  2: print "vingt";
  2071.                     if (n%10 == 1) { print " et un"; return; }
  2072.                  3: print "trente";
  2073.                     if (n%10 == 1) { print " et un"; return; }
  2074.                  4: print "quarante";
  2075.                     if (n%10 == 1) { print " et un"; return; }
  2076.                  5: print "cinquante";
  2077.                     if (n%10 == 1) { print " et un"; return; }
  2078.                  6: print "soixante";
  2079.                     if (n%10 == 1) { print " et un"; return; }
  2080.                  7: print "soixante";
  2081.                     if (n%10 == 1) { print " et onze"; return; }
  2082.                     print "-"; LanguageNumber(10 + n%10); return;
  2083.                  8: if (n%10 == 0) { print "quatre vingts"; return; }
  2084.                     print "quatre-vingt";
  2085.                  9: print "quatre-vingt-"; LanguageNumber(10 + n%10); return;
  2086.               }
  2087.               if (n%10 ~= 0)
  2088.               {   print "-"; LanguageNumber(n%10);
  2089.               }
  2090.       }
  2091.     ];
  2092.  
  2093. To test this, you may want to run the routine
  2094.  
  2095.     [ TestNumbers n;
  2096.       for (n = -1001: n<=1001: n++) print (number) n, "^";
  2097.     ];
  2098.  
  2099. (if you have the patience), or
  2100.  
  2101.     [ TestRNumbers n x y;
  2102.       for (n = 1: n<=100: n++)
  2103.       {   x = random(32767);
  2104.           y = random(2); if (y == 0) y = -1;
  2105.           print (number) x*y, "^";
  2106.       }
  2107.     ];
  2108.  
  2109. (if you haven't).
  2110.  
  2111.  
  2112.    L.IV.5  How to print: the time of day
  2113.    -------------------------------------
  2114.  
  2115. Next, a routine called LanguageTimeOfDay should appear, to print out the
  2116. time of day in a suitable (numeric) style.  Here is the French version:
  2117.  
  2118.    [ LanguageTimeOfDay hours mins;
  2119.      print hours/10, hours%10, "h", mins/10, mins%10;
  2120.    ];
  2121.  
  2122. and here the corresponding English version:
  2123.  
  2124.    [ LanguageTimeOfDay hours mins i;
  2125.        print (string) TIME__TX;
  2126.        i=hours%12; if (i<10) print " ";
  2127.        if (i==0) i=12;
  2128.        print i, ":", mins/10, mins%10;
  2129.        if ((hours/12) > 0) print " pm"; else print " am";
  2130.    ];
  2131.  
  2132. so that 23 minutes past 1 in the afternoon would be printed as
  2133.  
  2134.     13h23         1:23 pm
  2135.  
  2136. according to national custom.
  2137.  
  2138.  
  2139.    L.IV.6  How to print: verbs
  2140.    ---------------------------
  2141.  
  2142. Inform sometimes needs to print verbs out, in messages like:
  2143.  
  2144.    I only understood you as far as wanting to take the red box.    (*)
  2145.                                               ^^^^
  2146.  
  2147. It normally does this by simply printing out the verb's dictionary entry.
  2148. However, dictionary entries tend to be cut short (to the first 9 letters
  2149. or so) or else to be abbreviations (like "i" meaning "inventory").
  2150. This routine must look at its argument and either print a textual form and
  2151. return true, or return false (letting the library carry on as normal):
  2152.  
  2153.    [ LanguageVerb i;
  2154.      if (i==#n$l)        { print "look";              rtrue; }
  2155.      if (i==#n$z)        { print "wait";              rtrue; }
  2156.      if (i==#n$x)        { print "examine";           rtrue; }
  2157.      if (i==#n$i or 'inv' or 'inventory')
  2158.                          { print "inventory";         rtrue; }
  2159.      rfalse;
  2160.    ];
  2161.  
  2162. It's probably better to avoid the need for the routine altogether in
  2163. languages where the verb stem would make no sense, by changing the
  2164. message (*) above to make it less explicit.
  2165.  
  2166.  
  2167.    L.IV.7  How to print: menus
  2168.    ---------------------------
  2169.  
  2170. Next, a batch of definitions should be made to specify the look of menus
  2171. and which keys on the keyboard navigate through them.  "French.h" has:
  2172.  
  2173.     Constant NKEY__TX     = "P = prochain    ";
  2174.     Constant PKEY__TX     = "D = dernier ";
  2175.     Constant RKEY__TX     = "ENTER = lire sujet   ";
  2176.     Constant QKEY1__TX    = "  R = retour     ";
  2177.     Constant QKEY2__TX    = "R = dernier carte";
  2178.  
  2179.     Constant NKEY1__KY    = 'P';
  2180.     Constant NKEY2__KY    = 'p';
  2181.     Constant PKEY1__KY    = 'D';
  2182.     Constant PKEY2__KY    = 'd';
  2183.     Constant QKEY1__KY    = 'R';
  2184.     Constant QKEY2__KY    = 'r';
  2185.  
  2186. whereas "English.h" has:
  2187.  
  2188.     Constant NKEY__TX     = "N = next subject";
  2189.     Constant PKEY__TX     = "P = previous";
  2190.     Constant QKEY1__TX    = "  Q = resume game";
  2191.     Constant QKEY2__TX    = "Q = previous menu";
  2192.     Constant RKEY__TX     = "RETURN = read subject";
  2193.  
  2194.     Constant NKEY1__KY    = 'N';
  2195.     Constant NKEY2__KY    = 'n';
  2196.     Constant PKEY1__KY    = 'P';
  2197.     Constant PKEY2__KY    = 'p';
  2198.     Constant QKEY1__KY    = 'Q';
  2199.     Constant QKEY2__KY    = 'q';
  2200.  
  2201.  
  2202.    L.IV.8  How to print: miscellaneous short messages
  2203.    --------------------------------------------------
  2204.  
  2205. These are phrases or words so short that they're not worth putting in the
  2206. LibraryMessages system, e.g.,
  2207.  
  2208.    Constant SCORE__TX    = "Score: ";
  2209.    Constant MOVES__TX    = "Tours: ";
  2210.    Constant TIME__TX     = "Heure: ";
  2211.  
  2212. define the text printed on the ordinary status line (in English, "Score" and
  2213. "Turns").  The remainder of the list is as follows:
  2214.  
  2215.    Constant CANTGO__TX   = "On ne peut pas aller en cet direction.";
  2216.        the "You can't go that way" message
  2217.    Constant FORMER__TX   = "votre m@^eme ancien";
  2218.        name of player's former self, after the player has become
  2219.        somebody else
  2220.    Constant YOURSELF__TX = "votre m@^eme";
  2221.        name of player object
  2222.    Constant DARKNESS__TX = "Obscurit@'e";
  2223.        name of Darkness place
  2224.    Constant NOTHING__TX  = "rien";
  2225.        name of the "nothing" object (caused by print (name) 0;, which
  2226.        is not strictly speaking legal in Inform anyway)
  2227.  
  2228.    Constant THOSET__TX   = "ces choses";
  2229.        used in command printing
  2230.    Constant THAT__TX     = "@cca";
  2231.        used in command printing. There are three circumstances in which
  2232.        all or part of a command can be printed by the parser:
  2233.  
  2234.            > TAKE OUT
  2235.            What do you want to take out?        [an incomplete command]
  2236.  
  2237.            > TAKE FROG
  2238.            (the lesser-spotted frog)            [a vague command]
  2239.  
  2240.            > TAKE FROG WITHIN CAGE
  2241.            I only understood you as far as wanting to take the frog.
  2242.                                                 [a command that went on
  2243.                                                 too long]
  2244.  
  2245.        "those" is printed in place of a multiple object and "that"
  2246.        in place of a number or something not well understood by the
  2247.        parser (like a question topic).  Note that
  2248.        
  2249.            What do you want to 
  2250.            I only understood you as far as wanting to 
  2251.  
  2252.        are both library messages.  The verb is printed from its dictionary
  2253.        entry (via LanguageVerb above), and will therefore appear in the
  2254.        imperative.  (In English, of course, this is the same as the
  2255.        infinitive.)  You may therefore want to rephrase the two messages as
  2256.        
  2257.            What do want to finish the command: 
  2258.            I only understood the first part of your command:
  2259.  
  2260.  
  2261.    Constant OR__TX       = " ou ";
  2262.        in the list of objects being printed in a question asking you
  2263.        which thing you mean: if you can't find anything grammatical to
  2264.        go here, try using just ", ".
  2265.  
  2266.    Constant AND__TX      = " et ";
  2267.        dividing up many kinds of list
  2268.  
  2269.    Constant WHOM__TX     = "qui ";
  2270.    Constant WHICH__TX    = "lequel ";
  2271.    Constant IS2__TX      = "est ";
  2272.    Constant ARE2__TX     = "sont ";
  2273.        used _only_ to print text like
  2274.        "inside which is a duck", "on top of whom are two drakes"
  2275.  
  2276.    Constant IS__TX       = " est";
  2277.    Constant ARE__TX      = " sont";
  2278.        used only by the list-maker and only when the ISARE_BIT is set;
  2279.        the library only does this from with LibraryMessages, so you
  2280.        can avoid the need altogether
  2281.  
  2282.  
  2283.    L.IV.9  How to print: LibraryMessages
  2284.    -------------------------------------
  2285.  
  2286. Finally, Part IV contains an extensive block of translated library messages,
  2287. making up at least 50% of the language definition file.  In English they look
  2288. like this:
  2289.  
  2290.   ...
  2291.   Lock:    switch(n)
  2292.            {   1: if (x1 has pluralname) print "They don't ";
  2293.                   else print "That doesn't ";
  2294.                   "seem to be something you can lock.";
  2295.                2: print_ret (ctheyreorthats) x1, " locked at the moment.";
  2296.                3: "First you'll have to close ", (the) x1, ".";
  2297.                4: if (x1 has pluralname) print "Those don't ";
  2298.                   else print "That doesn't ";
  2299.                   "seem to fit the lock.";
  2300.                5: "You lock ", (the) x1, ".";
  2301.            }
  2302.  
  2303.   SwitchOn: switch(n)
  2304.            {   1: print_ret (ctheyreorthats) x1,
  2305.                   " not something you can switch.";
  2306.                2: print_ret (ctheyreorthats) x1,
  2307.                   " already on.";
  2308.                3: "You switch ", (the) x1, " on.";
  2309.            }
  2310.   ...
  2311.  
  2312. You have to translate these messages, or near equivalents to them.  It may
  2313. be useful to define printing rules, just as I've done in "English.h":
  2314.  
  2315.    [ CTheyreorThats obj; if (obj has pluralname) print "They're";
  2316.      else print "That's";
  2317.    ];
  2318.  
  2319. (Thus, "ctheyorthats" is not a rule built into Inform but is one I wrote
  2320. into the language definition file.)
  2321.  
  2322. ------------------------------------------------------------------------------
  2323.